﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using ADV_Evaluator.Command;
using Yanesdk.Draw;
using Yanesdk.Input;
using SD = System.Drawing;
using YD = Yanesdk.Draw;

namespace ADV_Evaluator
{

	/// <summary>
	/// メニューウィンドウ
	/// </summary>
	class Window_Menu : Window_Base
	{

        private int screenWidth, screenHeight;
        private string[] options;
        private int selectedIndex;
        private bool isDecided;
        private int mouseX, mouseY;
        private Rectangle cursorRect;
        private Brush cursorBrush;
        private bool init;

        #region プロパティ
        /// <summary>
        /// 選択中のメニュー番号（0..[項目数-1]）
        /// </summary>
        public int SelectedIndex {
            get { return selectedIndex; }
            set {
                if (options == null) {
                    selectedIndex = 0;
                } else {
                    if (value < 0) {
                        do {
                            selectedIndex = options.Length + value;
                        } while (selectedIndex >= options.Length);
                    } else {
                        selectedIndex = value % options.Length;
                    }
                    Refresh();
                }
            }
        }
        /// <summary>
        /// 選択中のメニュー文字列
        /// </summary>
        public string SelectedText {
            get {
                if (options == null) {
                    return null;
                } else {
                    return options[selectedIndex];
                }
            }
        }
        /// <summary>
        /// 現在メニューを表示中かどうか
        /// </summary>
        public bool IsActive {
            get { return options != null; }
        }
        /// <summary>
        /// マウスやキーボード入力で選択が確定したらtrueになる
        /// </summary>
        public bool IsDecided {
            get { return isDecided; }
            set { isDecided = value; }
        }
        /// <summary>
        /// 可視状態。代入は内部からのみ。外部からはShowかHideでいじること。
        /// </summary>
        new public bool Visible {
            get { return base.Visible; }
            private set { base.Visible = value; }
        }
        #endregion

        /// <summary>
        /// 初期化
        /// </summary>
        public Window_Menu(int screenWidth, int screenHeight)
            : base(1, 1) {  // 大きさは後で決める
            // 初期状態では非表示
            this.Visible = false;
            // サイズを保存
            this.screenWidth = screenWidth;
            this.screenHeight = screenHeight;
            // インスタンス変数の設定
            this.options = null;
            this.mouseX = this.mouseY = 0;
            this.isDecided = false;
        }

        /// <summary>
        /// カーソル矩形を得る
        /// </summary>
        /// <param name="selectedIndex"></param>
        /// <returns></returns>
        private Rectangle GetCursorRect(int selectedIndex) {
            Rectangle rect = new Rectangle();
            rect.X = BorderWidth + Padding;
            rect.Y = BorderWidth + Padding;
            rect.Width = width - BorderWidth * 2 - Padding * 2;
            rect.Height = (int)(font.Size * 1.5);
            rect.Y += rect.Height * selectedIndex;
            return rect;
        }

        /// <summary>
        /// 項目を指定し、表示する。
        /// </summary>
        /// <param name="option"></param>
        public void Show(string[] options) {
            this.options = options;
            int width = screenWidth / 5 * 1;
            int height = (int)(font.Size * 1.5 * options.Length) + BorderWidth * 2 + Padding * 2;
            this.x = 3;
            this.y = 3;
            this.cursorRect = GetCursorRect(0);
            this.cursorBrush = new SolidBrush(Color.FromArgb(100, Color.White));
            this.selectedIndex = 0;
            Resize(width, height);
            Refresh();
            this.Visible = true;
            this.isDecided = false;
            this.init = false;
        }

        /// <summary>
        /// メニューの表示を終了する
        /// </summary>
        public void Hide() {
            this.options = null;
            this.selectedIndex = -1;
            this.isDecided = false;
            this.mouseX = this.mouseY = 0;
            this.Visible = false;
        }

        /// <summary>
        /// 再描画
        /// </summary>
        public override void Refresh() {
            if (!IsActive) {
                return;
            }
            DrawBackground();
            DrawOptions();
            texture.SetBitmap(bitmap);
        }

        /// <summary>
        /// メニュー文字列を描画
        /// </summary>
        private void DrawOptions() {
            using (StringFormat sf = new StringFormat(StringFormatFlags.NoWrap))
            using (Graphics graphics = Graphics.FromImage(bitmap)) {
                graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
                sf.LineAlignment = StringAlignment.Center;
                for (int i = 0; i < options.Length; i++) {
                    Rectangle rect = GetCursorRect(i);
                    // カーソル矩形の描画
                    if(i == selectedIndex){
                        graphics.FillRectangle(cursorBrush, rect);
                    }
                    // テキストの描画
                    graphics.DrawString(options[i], font, textBrush, rect, sf);
                }
            }
        }

        /// <summary>
        /// マウスポインタの位置にある項目のインデックスを返す。
        /// </summary>
        /// <param name="mx">マウスx座標</param>
        /// <param name="my">マウスy座標</param>
        /// <returns>インデックス。存在しなければ-1。</returns>
        private int GetMouseHoveredIndex(int mx, int my) {
            // ウィンドウ上にマウスポインタが無ければ除外
            if (!this.Rect.Contains(mx, my)) {
                return -1;
            }
            // マウスポインタのあるインデックスを探し、カーソルを描画
            for (int i = 0; i < options.Length; i++) {
                // カーソル矩形
                Rectangle rect = GetCursorRect(i);
                // ウィンドウの位置の分ずらす
                rect.Offset(this.Rect.Location);
                if (rect.Contains(mx, my)) {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// マウスポインタのあるところの項目にカーソルを出す
        /// </summary>
        /// <param name="mouse">マウス</param>
        private void ShowMouseCursor(MouseInput mouse) {
			if (!base.Enable)
			{ return; }
			// マウスポインタの座標を求める
            int mx, my;
            mouse.GetPos(out mx, out my);
            // 前回調べたときからマウスが動いていなければ除外する
            if (mx == mouseX && my == mouseY) {
                return;
            }
            mouseX = mx;
            mouseY = my;
            // インデックスを求める
            int index = GetMouseHoveredIndex(mx, my);
            // インデックスがあり、現在の値と違うなら、再描画する
            if (index != -1 && index != selectedIndex) {
                selectedIndex = index;
                Refresh();
            }
        }

        /// <summary>
        /// キーが押されたり、カーソル上でマウスがクリックされたら、IsDecidedをtrueにする。
        /// これをシーン側で感知して次へ進める。
        /// </summary>
        /// <param name="keyboard">キーボード</param>
        /// <param name="mouse">マウス</param>
        private void CheckDecided(KeyBoardInput keyboard, MouseInput mouse) {
			if (!base.Enable)
			{ return; }
			// 最初の呼び出しはなんかバグるから除外する
            if (!init) {
                init = true;
                return;
            }
            // キーが押されていればIsDecidedフラグを立てる
            if(keyboard.IsPush(KeyCode.RETURN) || keyboard.IsPush(KeyCode.SPACE)){
                isDecided = true;
            }
            // マウスがクリックされたとき
            else if (mouse.IsPush(MouseInput.Button.Left)) {
                // マウスポインタの座標を求める
                int mx, my;
                mouse.GetPos(out mx, out my);
                // インデックスを求める
                int index = GetMouseHoveredIndex(mx, my);
                // インデックスがあればIsDecidedフラグを立てる
                if (index != -1) {
                    isDecided = true;
                }
            }
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="system"></param>
        public override void Update(GameSystem system) {
			// 項目がセットされていなければダメ
            if (!IsActive) {
               return;
            }
			if (!base.Enable)
			{
				// テクスチャの転送
				base.Update(system);
				return;
			}
			// キーボードの↓キーが押されていれば、インデックスを下に
            if (system.Keyboard.IsPush(KeyCode.DOWN)) {
                SelectedIndex++;
            // キーボードの↑キーが押されていれば、インデックスを上に
            } else if (system.Keyboard.IsPush(KeyCode.UP)) {
                SelectedIndex--;            
            } else {
                // マウスポインタのあるところの項目にカーソルを出す
                ShowMouseCursor(system.Mouse);
                // キーやマウスが押されたら選択済みフラグを立てる
                CheckDecided(system.Keyboard, system.Mouse);
            }
            // テクスチャの転送
            base.Update(system);
        }

        /// <summary>
        /// 解放
        /// </summary>
        public override void Dispose() {
            base.Dispose();
        }

    }
}
